#include "Dri_18B20.h"

sbit B_7 = B ^ 7;

/**
 * @brief 初始化
 *
 */
bit Dri_18B20_Init()
{
    bit res;
    // 初始化
    // 拉低DQ，发送复位脉冲，最少持续480us
    DQ = 0;
    Delay_480us();
    DQ = 1;

    // 接收数据
    // 60us之后读取DQ上的数据, DQ如果是0表示存在从设备
    Delay_60us();
    res = ~DQ;
    Delay_480us();

    return res;
}

/**
 * @brief 发送数据
 *
 * @param send_Data 发送对应的数据
 */
void Dri_18B20_Send(u8 send_Data)
{
    u8 i;
    for (i = 0; i < 8; i++) {
        // 拉低
        DQ = 0;
        Delay_15us();
        // 添加数据
        DQ = send_Data & 0X01;
        send_Data >>= 1;
        Delay_60us();
        DQ = 1;
    }
}

/**
 * @brief 接收数据
 *
 * @param send_Data 接收数据
 */
u8 Dri_18B20_Receive()
{
    u8 i;
    u8 res;
    for (i = 0; i < 8; i++) {
        // 拉低
        DQ = 0;
        DQ = 1;
        Delay_15us();
        B >>= 1;
        B_7 = DQ;

        // 延时50us
        Delay_60us();
        // 释放总线
        DQ = 1;
    }
    res = B;
    return res;
}

/**
 * @brief 获取温度数据
 *
 * @return u8
 */
u8 Dri_18B20_GetTemperature()
{
    u8 ls_byte;
    u8 ms_byte;
    // 初始化
    Dri_18B20_Init();
    // 1. 发送数据,跳过设备地址,发送跳过ROM命令
    Dri_18B20_Send(0XCC);
    // 2. 温度转换[0x44]
    Dri_18B20_Send(0x44);

    // 初始化
    Dri_18B20_Init();
    // 1. 发送数据,跳过设备地址,发送跳过ROM命令
    Dri_18B20_Send(0XCC);
    // 2. 读取暂存寄存器 [0xBE]
    Dri_18B20_Send(0xBE);
    // 3. 暂存器中获取数据
    ls_byte = Dri_18B20_Receive();
    ms_byte = Dri_18B20_Receive();

    // 处理结果并返回
    return (ms_byte << 4) | (ls_byte >> 4);
}

/**
 * @brief 测温并返回测温结果
 *
 * @return char 测温结果
 */
float Int_18B20_GetTempearatureFloat()
{
    u8 lsb_byte, msb_byte;

    // 第一次通信 进行温度转换将结果存入暂存器 --------------------------------
    // 1. 初始化：发送复位脉冲
    Dri_18B20_Init();
    // 2. 发送ROM命令：跳过
    Dri_18B20_Send(0xCC);
    // 3. 发送功能命令: 温度转换
    Dri_18B20_Send(0x44);

    // 第二次通信 读取暂存器结果 ---------------------------------------------
    // 1. 初始化：发送复位脉冲
    Dri_18B20_Init();
    // 2. 发送ROM命令：跳过
    Dri_18B20_Send(0xCC);
    // 3. 发送功能命令: 读取暂存器
    Dri_18B20_Send(0xBE);
    // 4. 接收前两个字节
    lsb_byte = Dri_18B20_Receive();
    msb_byte = Dri_18B20_Receive();
    // 5. 处理结果并返回
    return ((msb_byte << 4) | (lsb_byte >> 4)) + (lsb_byte & 0x0F) * 0.0625;
}